package com.smartfast4j.redis;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;

import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 基于RedisTemplate客户端实现
 */
@Component //@component （把普通pojo实例化到spring容器中，相当于配置文件中的<bean id="" class=""/>）
public class RedisClientImpl implements RedisClient {

	private static final Logger logger = Logger.getLogger(RedisClientImpl.class);

	/**
	 * RedisTemplate中定义了对5种数据结构操作
		 redisTemplate.opsForValue();//操作字符串
		 redisTemplate.opsForHash();//操作hash
		 redisTemplate.opsForList();//操作list
		 redisTemplate.opsForSet();//操作set
		 redisTemplate.opsForZSet();//操作有序set
	 */
	@Autowired
	private RedisTemplate redisTemplate;

	@Override
	public String get(String key) {
		try {
			ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
			String result = valueOperations.get(key);
			return result;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return "";
		}
	}

	@Override
	public byte[] get(byte[] key) {
		String data = get(new String(key));
		if(data!=null){
			return data.getBytes();
		}else{
			return null;
		}
	}

	@Override
	public void set(String key, String value) {
		try {
			ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
			//设置值
			valueOperations.set(key, value);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	@Override
	public void set(String key, String value, int expire) {
		try {
			BoundValueOperations<String, String> boundValueOperations = redisTemplate.boundValueOps(key);
			//设置值
			boundValueOperations.set(value, expire, TimeUnit.SECONDS);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	@Override
	public void set(byte[] key, byte[] value) {
		set(new String(key),new String(value));
	}

	@Override
	public void set(byte[] key, byte[] value, int expire) {
		set(new String(key),new String(value),expire);
	}

	/*@Override
	public String hget(String hkey, String key) {
		try {
			//操作hash
			Object value = redisTemplate.opsForHash().get(hkey,key);
			if(value!=null){
				return value.toString();
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
		return null;
	}*/

	@Override
	public <T> T hget(String hkey, T key) {
		HashOperations<String, T,T> hashOperations = redisTemplate.opsForHash();
		return hashOperations.get(hkey,key);
	}

	/*@Override
	public void hset(String hkey, String key, String value) {
		try {
			//操作hash
			redisTemplate.opsForHash().put(hkey,key,value);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}*/

	@Override
	public <T> void hset(String hkey, T key, T value) {
		HashOperations<String, T, T> hashOperations = redisTemplate.opsForHash();
		hashOperations.put(hkey,key,value);
	}

	@Override
	public long incr(String key) {
		long no = redisTemplate.opsForValue().increment(key, 1);
		return no;
	}

	@Override
	public Long incr(String key, long integer) {
		try {
			long no = redisTemplate.opsForValue().increment(key, integer);
			return no;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return 0L;
		}
	}

	@Override
	public Double incr(String key, double value) {
		try {
			Double no = redisTemplate.opsForValue().increment(key, value);
			return no;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return 0D;
		}
	}

	@Override
	public Long decr(String key) {
		return redisTemplate.opsForValue().increment(key,-1);
	}

	@Override
	public Long decr(String key, long integer) {
		return redisTemplate.opsForValue().increment(key,-integer);
	}

	@Override
	public void expire(String key, int second) {
		redisTemplate.expire(key,second,TimeUnit.SECONDS);
	}

	@Override
	public long ttl(String key) {
		return redisTemplate.getExpire(key,TimeUnit.SECONDS);
	}

	@Override
	public void del(String key) {
		redisTemplate.delete(key);
	}

	@Override
	public void hdel(String hkey, String key) {
		redisTemplate.opsForHash().delete(hkey,key);
	}

	@Override
	public void del(byte[] key) {
		del(new String(key));
	}

	@Override
	public <T> void setObject(String key, T obj) {
		ValueOperations<String, T> valueOperations = redisTemplate.opsForValue();
		//设置值
		valueOperations.set(key, obj);
	}

	@Override
	public <T> T getObject(String key, Class<T> clazz) {
		try {
			return (T) redisTemplate.boundValueOps(key).get();
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return null;
		}
	}

	@Override
	public Set<String> keys(String pattern) {
		try {
			Set<String> set = redisTemplate.keys(pattern + "*");
			return set;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return null;
		}
	}

	@Override
	public void  flushDB() {
		redisTemplate.execute(new RedisCallback() {
			public String doInRedis(RedisConnection connection) throws DataAccessException {
				connection.flushDb();
				return "ok";
			}
		});
	}

	@Override
	public Long dbSize() {
		return (Long)redisTemplate.execute(new RedisCallback() {
			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.dbSize();
			}
		});
	}
}
